<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2019/1/15
 * Time: 23:05
 */
namespace app\admin\logic;


use app\common\utils\Utils;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use think\exception\ValidateException;

class ExportService
{
    private static $new; //申请一个私有的静态成员变量来保存该类的唯一实例
    private $data;  //要导出的数据

    /**
     * worksheet对象
     * @var object \PhpOffice\PhpSpreadsheet\Spreadsheet;
     */
    private static $spreadsheet;
    private static $config;
    private $sheet = [];
    /**
     * worksheet对象
     * @var object \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
     */
    private $curSheet;
    private static $style = [];
    public function __construct() {
        ini_set('memory_limit','256M');  //提升内存使用量
        //样式变量
       self::$style = [
            //设置字体样式
            'font' => [
                'name' => 'Arial',
                'bold' => true,
                'type' => Fill::FILL_SOLID,
                'color' => [
                    'rgb' => '000000'
                ]
            ],
            //设置边框线样式
            'borders' => [
                //allBorders所有的边框线样式
                //左边框线
                'bottom' => [
                    'borderStyle' => Border::BORDER_DASHDOT,
                    'color' => [
                        'rgb' => '808080'
                    ]
                ],
                //上边框线
                'top' => [
                    'borderStyle' => Border::BORDER_DASHDOT,
                    'color' => [
                        'rgb' => '808080'
                    ]
                ]
            ],
            'alignment' => [
                'horizontal' => Alignment::HORIZONTAL_CENTER,
                'vertical' => Alignment::VERTICAL_CENTER,
                'wrapText' => true,
            ],
        ];

    }


    public static function instance () { //声明一个静态公共方法，供外部获取唯一实例
        if (!(self::$new instanceof self)) {
            self::$new = new self;
        }

        self::$spreadsheet = new Spreadsheet();
        self::$config = config('site.export_config');
        self::$spreadsheet->getDefaultStyle()->getFont()->setName(self::$config['font'])->setSize(self::$config['size']);
        self::$spreadsheet->getDefaultStyle()->applyFromArray(self::$style);
        return self::$new;
    }

    /**
     * 设置表格信息
     * @param $config
     * @return  $this;
     */
    public function setTitles($config) {

        self::$spreadsheet->getProperties()
            ->setCreator($config['author'])  //作者
            ->setTitle($config['title'])     //标题
            ->setSubject($config['subject']);

        return $this;
    }
    /**
     * 创建sheet
     * @param $title //标题
     * @return  $this;
     */
    public function createSheet($title, $index = 0) {
        $sheet = self::$spreadsheet->createSheet($index);
        $sheet->setTitle($title);
        $this->curSheet = $sheet;
        array_push($this->sheet, $sheet);
        return $this;
    }
    /**
     * 设置sheet的头部
     * @var \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
     * $headers  'name' => [14,14,15]   //0开始列  1结束列  0 = 1表示不跨列  2为宽度
     * @return   $this;
     */
    public function setSheetHeader($line, $headers) {
        if (!$this->curSheet) {
            throw new ValidateException('请先创建sheet');
        }
        foreach ($headers as $k => $v) {
            $this->curSheet->getStyleByColumnAndRow($v[0], $line)->getAlignment()
                ->setWrapText(true)
                ->setHorizontal(Alignment::HORIZONTAL_CENTER)
                ->setVertical(Alignment::VERTICAL_CENTER);

            if (isset($v[2])) {
                $this->curSheet->getColumnDimensionByColumn($v[0])->setWidth($v[2]);
            }
            $this->curSheet->setCellValueByColumnAndRow($v[0],$line, $k);
            if ($v[0] != $v[1]) {
                $this->curSheet->mergeCellsByColumnAndRow($v[0], $line, $v[1], $line);
            }
        }

        return $this;
    }
    /**
     * 把数据填充到表格中
     * @param $values
     * @param $line
     * @return $this
     */
    public function insertValues($line, $values = null) {
        //如果传递了$data 修改一下$data
        if (!$values) {
            return $this;
        }

        foreach ($values as $k1 => $v1) {
            $col = $k1 +1;
            $this->curSheet->getStyleByColumnAndRow($col, $line)->getAlignment()
                ->setWrapText(true)
                ->setHorizontal(Alignment::HORIZONTAL_CENTER)
                ->setVertical(Alignment::VERTICAL_CENTER);
            $this->curSheet->setCellValueByColumnAndRow($col, $line, $v1, DataType::TYPE_STRING);
            $this->curSheet->getStyleByColumnAndRow($col, $line)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_TEXT);
        }

        return $this;
    }

    public function write($type = 'Xlsx',$name) {
        @ob_end_clean();//清除缓冲区,避免乱码
        $writer = IOFactory::createWriter(self::$spreadsheet, $type);
        $dir1 = '/export/' . $name .'.'.strtolower($type);
        $dir = ROOT_PATH . '/public' . $dir1;
        $name = basename($dir);
        $dir_create = dirname($dir);
        Utils::directory($dir_create);
        $writer->save($dir_create . '/' . $name);
        return $dir1;
    }

    public function output($type = 'Xlsx',$name) {
        $name = $name .'.'.strtolower($type);
        ob_end_clean();//清除缓冲区,避免乱码
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $name);
        header('Cache-Control: max-age=0');
        // If you're serving to IE 9, then the following may be needed
        header('Cache-Control: max-age=1');

        // If you're serving to IE over SSL, then the following may be needed
        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
        header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
        header('Pragma: public'); // HTTP/1.0

        $writer = IOFactory::createWriter(self::$spreadsheet, $type);
        $writer->save('php://output');
        return true;
    }

    public function __destruct()
    {
        self::$spreadsheet->disconnectWorksheets();
        self::$spreadsheet = null;
    }

    private function __clone() {} //声明私有的克隆方法，防止对象被克隆

    public function __sleep() { //重写__sleep方法，将返回置空，防止序列化反序列化获得新的对象
        return [];
    }
}